package com.hb.config;

import com.hb.impl.*;
import com.hb.interfaces.CompactDisc;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 创建 JavaConfig 类的关键在于为其添加 @Configuration 注解，@Configuration 注解表明这个类是一个配置类
@Configuration
public class CDPlayerConfig {
    // 1、要在 JavaConfig 中声明 bean，我们需要编写一个方法，这个方法会创建所需类型的实例，然后给这个方法添加 @Bean 注解。
    // 2、@Bean 注解会告诉 Spring 这个方法将会返回一个对象，该对象要注册为 Spring 应用上下文中的 bean。方法体中包含了最终产生 bean 实例的逻辑。
    // 3、默认情况下，bean 的 ID 与带有 @Bean 注解的方法名是一样的。在本例中，bean 的名字将会是 sgtPeppers。
    // 如果你想为其设置成一个不同的名字的话，那么可以重命名该方法，也可以通过 name 属性指定一个不同的名字：@Bean("otherCompactDisc") 或 @Bean(name = "otherCompactDisc")
    @Bean
    public CompactDisc sgtPeppers() {
        return new SgtPeppers();
    }

//    @Bean
//    public CompactDisc randomBeatlesCD() {
//        int choice = (int) Math.floor(Math.random() * 4);
//        if (choice == 0) {
//            return new SgtPeppers();
//        } else if (choice == 1) {
//            return new WhiteAlbum();
//        } else if (choice == 2) {
//            return new HardDaysNight();
//        } else {
//            return new Revolver();
//        }
//    }

    @Bean
    public CDPlayer cdPlayer() {
        // 1、在 JavaConfig 中装配 bean 的最简单方式就是引用所需要的其他创建 bean 的方法。
        // 2、使用下面这种装配方式的话需要用构造方法进行依赖注入
        // 3、看起来，CompactDisc 是通过调用 sgtPeppers() 得到的，但情况并非完全如此。因为 sgtPeppers() 方法上添加了@Bean注解，
        // Spring 将会拦截所有对它的调用，并确保直接返回该方法所创建的 bean，而不是每次都对其进行实际的调用。
        return new CDPlayer(sgtPeppers());
    }

    // 下面这个 bean 其实和上面这个是完全一样的，并不是另一个 CDPlayer 类型的 bean，由于 Spring 中的 bean 默认都是单例的，
    // 所以两个 CDPlayer 类型的 bean 会得到相同的 SgtPeppers 实例
    @Bean
    public CDPlayer anotherCDPlayer() {
        return new CDPlayer(sgtPeppers());
    }

    // 1、这是另一种装配 bean 的方式
    // 2、借助这种技术，cdPlayer() 方法也能够将 CompactDisc 注入到 CDPlayer 的构造器中，而且不用明确引用 CompactDisc 的 @Bean 方法。
    // 3、通过这种方式引用其他的 bean 通常是最佳的选择，因为它不会要求将 CompactDisc 声明到同一个配置类之中。在这里甚至没有要求 CompactDisc 必须要在 JavaConfig 中声明，
    // 实际上它可以通过组件扫描功能自动发现或者通过 XML 来进行配置。你可以将配置分散到多个配置类、XML 文件以及自动扫描和装配 bean 之中，只要功能完整健全即可。
    // 不管 CompactDisc 是采用什么方式创建出来的，Spring 都会将其传入到配置方法中，并用来创建 CDPlayer bean。
    @Bean
    public CDPlayer cdPlayer1(CompactDisc compactDisc) {
        return new CDPlayer(compactDisc);
    }

    // 通过 Setter 方法注入 CompactDisc
    @Bean
    public CDPlayer cdPlayer2(CompactDisc compactDisc) {
        CDPlayer cdPlayer = new CDPlayer(compactDisc);
        cdPlayer.setCompactDisc(compactDisc);
        return cdPlayer;
    }

    @Bean
    public CDPlayer cdPlayerSetter() {
        CDPlayer player = new CDPlayer(sgtPeppers());
        player.setCompactDisc(sgtPeppers());
        return player;
    }
}
